package pl.edu.agh.gt;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import pl.edu.agh.gt.data.DataProvider;
import pl.edu.agh.gt.data.Rate;
import pl.edu.agh.gt.data.RatesHistory;
import pl.edu.agh.gt.gui.ChartDisplay;
import pl.edu.agh.gt.stock.Broker;
import pl.edu.agh.gt.stock.Trader;
import pl.edu.agh.gt.strategy.BuyAndHold;
import pl.edu.agh.gt.strategy.GreedyStrategy;
import pl.edu.agh.gt.strategy.Strategy;

/**
 * BASE = USD QUOTE = EUR
 * 
 * private/protected
 * 
 * asercje
 * 
 * @author kpajak
 * 
 */

public class Stock {

	private final static Logger log = Logger.getLogger(Stock.class);

	private RatesHistory ratesHistory;
	private Broker broker;

	private Map<String, Trader> traders;

	public Stock(String path, Date start, Date end) throws IOException {
		ratesHistory = DataProvider.readData(new File(path)).getPeriod(start, end);
		broker = new Broker();
		traders = new HashMap<String, Trader>();
	}

	public Stock(RatesHistory rates) {
		ratesHistory = rates;
		broker = new Broker();
		traders = new HashMap<String, Trader>();
	}

	public void runStock() {

		List<Rate> rates = ratesHistory.asSortedList();
		Rate rate = rates.get(0);

		for (int i = 0; i < rates.size(); i++) {

			float diff = rates.get(i).getClose() / rate.getClose() - 1.0f;
			rate = rates.get(i);

			log.debug(" ------------ Time " + rate.getTime() + " ---  rate = " + rate.getClose() + " ------ \t DIFF = "
					+ diff);

			for (Trader t : traders.values()) {
				t.trade(i);
			}
		}

		// force traders to close positions at the end
		for (Trader t : traders.values())
			t.close(rate);

	}

	public void addTrader(Trader t) {
		traders.put(t.name, t);
	}

	public Trader getTrader(String name) {
		return traders.get(name);
	}

	public void removeTraders() {
		traders.clear();
	}

	public Broker getBroker() {
		return broker;
	}

	public RatesHistory getRatesHistory() {
		return ratesHistory;
	}

	/**
	 * Simulation with default params
	 */
	public static void main(String[] args) {

		try {
			Logger.getLogger("pl.edu.agh.gt.strategy").setLevel(Level.DEBUG);
			Logger.getLogger("pl.edu.agh.gt.stock").setLevel(Level.DEBUG);

			@SuppressWarnings("deprecation")
			Date start = new Date(2011 - 1900, 2, 7);

			@SuppressWarnings("deprecation")
			Date end = new Date(2011 - 1900, 2, 11);

			// Stock stock = new
			// Stock("C:\\Users\\kpajak\\Documents\\Studia\\MAGISTERA\\materialy_mgr\\EURUSD_hour.csv",start,end);
			Stock stock = new Stock("src/main/resources/EURUSD_hour.csv", start, end);

			createTraders(stock);

			stock.runStock();

			for (Trader t : stock.traders.values())
				log.info("Trader " + t.name + " total:" + t.evaluate(stock.ratesHistory.getLastRate())
						+ ", maxInvested: " + t.maxInvested);

			ChartDisplay.tradingChart("Trader performance compared to Buy&Hold", stock.ratesHistory,
					stock.getTrader("GREEDY").getTradingHistory(), stock.getTrader("BUY&HOLD").getTradingHistory());

		} catch (Exception e) {
			log.error("Stock exception", e);
		}

	}

	static void createTraders(Stock stock) {
		// lossTolerancy=10.971557 greedA=96.206276 desiredEarn=60.558296
		// enteringValue=3965.797 maxLoss=-94.22526
		
		// lossTolerancy=0.5157306 greedA=98.449036 desiredEarn=11.324305
		// enteringValue=3341.078 maxLoss=-97.571556
		
		// lossTolerancy=4.0945487 greedA=1182.5867 desiredEarn=121.56686
		// enteringValue=1930.7538 maxLoss=-94.29898 - malejacy - WOW
		
		// lossTolerancy=1.3363646 greedA=855.69104 desiredEarn=9.304913
		// enteringValue=640.66534 maxLoss=-147.75618
		Strategy strategy = new GreedyStrategy(1, 855.69104, 0, -147.75618, 9.304913, 640.66534, 1.3363646);
		stock.addTrader(new Trader("GREEDY", stock, strategy));

		strategy = new BuyAndHold();
		stock.addTrader(new Trader("BUY&HOLD", stock, strategy));

		// enable trade logging
		for (Trader t : stock.traders.values())
			t.setLogTrading(true);
	}

}
